#include "mainwindow.h"
#include "ui_mainwindow.h"
#include "painter.cpp"
#include <QPainter>
#include <QDebug>
#include <QFile>
#include <QMessageBox>
#include <QStringList>
#include <QStringListModel>
#include "model.h"

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    // UI init
    ui->setupUi(this);

    // load in qss style sheet
    loadStyleSheet(":/qss/mainWinSheet.qss");

    // bind value to UI component
    bindComponent();
    // set attributes' value of components
    buildInterface();

    validateCard.initialNull();

    // global QTimer
    timeRecorder->start(1000);
}

void MainWindow::loadStyleSheet(const QString &styleSheetFile)
{
    QFile file(styleSheetFile);
    file.open(QFile::ReadOnly);
    if (file.isOpen())
    {
        QString styleSheet = this->styleSheet();
        styleSheet += QLatin1String(file.readAll());//读取样式表文件
        this->setStyleSheet(styleSheet);//把文件内容传参
        file.close();
    }
    else
    {
        QMessageBox::information(this,"tip","cannot find qss file");
    }
}

void MainWindow::buildInterface()
{

    // Interface of panel
    userLog->print("User Log Intialization success...");
    motorLog->print("Motor Log Intialization success...");

    // Interface of monitor
    parkAreaUp->setSpacing(1);
    parkAreaDown->setSpacing(1);
    RoadPath->setSpacing(1);

    //initial free park area as 0
    freeArea->display(MAX_NUM_EACH_COLUMN*2);

    //initial parkArea with green background
    for(int i = 0; i < MAX_NUM_EACH_COLUMN; i++){

        QPushButton *btnUp   = new QPushButton(QString());
        QPushButton *btnDown = new QPushButton(QString());
        QPushButton *pathBtn=new QPushButton();

        buttonArray[0][i]    = btnUp;
        buttonArray[1][i]    = btnDown;
        movementPathArray[i] = pathBtn;

        btnUp->setObjectName(QString("%1").arg(-1));
        btnDown->setObjectName(QString("%1").arg(-1));

        btnUp->setStyleSheet("QPushButton{background:green;height:180px}");
        btnDown->setStyleSheet("QPushButton{background:green;height:180px}");
        pathBtn->setStyleSheet("QPushButton{background:black;width:10px;height:10px;border-radius:5px;margin-left:30px;margin-right:30px;}");

        parkAreaUp->addWidget(btnUp);
        parkAreaDown->addWidget(btnDown);
        RoadPath->addWidget(pathBtn);
    }

    //initial park system
    randomCardId          = "AAAAAA"; // set default flag
    animationParkPosition = -1;
    toPosition            = -1;
    fromPosition          = -1;
    waitTwoSecondEntence  = -1;
    waitTwoSecondExit     = 2;
    currentEntenceMovementPosition = 0;
    currentExitMovementPosition    = 0;

    //connect signal with slots
    parkSystem = ParkSystem();
    timer = new QTimer();
    timerExit = new QTimer();
    randomTimerEntence = new QTimer();
    randomTimerExit = new QTimer();
    isEntencing = false;
    isExiting = false;
    ExitTakenArea->setVisible(false);
    timeRecorder = new QTimer();
    timeRecord = new QTime(0,0,0,0);

//    connect(timer,SIGNAL(timeout()),this,SLOT(timeDone()));
//    connect(timerExit,SIGNAL(timeout()),this,SLOT(timeExitDone()));

    connect(this,SIGNAL(verifyEntranceSignals()),this,SLOT(disposalEntrance()));
    connect(this,SIGNAL(verifyExitSignals()),this,SLOT(disposalExit()));
    connect(timeRecorder,SIGNAL(timeout()),this,SLOT(eventTrigger()));
}

void MainWindow::buildInterface(Card *card)
{
    QPixmap pix;
    pix.load(card->getUserPic());
    userh->setPixmap(pix.scaled(109,129,Qt::KeepAspectRatio));
    userh->resize(129,109);
    qDebug() << "enter buildInterface...";

    id->setNum(card->getId());
    name->setText(card->getUsername());
}

// 事件处理逻辑
void MainWindow::eventTrigger(){
    // 全局计时器
    *timeRecord = timeRecord->addSecs(1);
    timeDisplayer->setText(timeRecord->toString("hh:mm:ss"));

    randomTimerEntranceDone(); // 每秒触发车辆进入事件
    randomTimerExitDone();     // 每秒触发车辆离开事件
    movePathPainter();         // 每秒绘制当前场内信息
}

void MainWindow::bindComponent(){

    // bind components of panel
    userh        = ui->userh;
    cardS        = ui->cards;
    id           = ui->id;
    name         = ui->name;
    plotNum      = ui->plotNum;
    logUserInfo  = ui->logUserInfo;
    logMotorInfo = ui->logMotorInfo;
    ExitTakenArea=ui->ExitTakenArea;

    userInfoModel = new QStringListModel(this);
    userLog = new Logger(userInfoModel,logUserInfo);

    motorInfoModel = new QStringListModel(this);
    motorLog = new Logger(motorInfoModel,logMotorInfo);

    // bind components of monitor
    parkAreaUp    = ui->ParkArea1;
    parkAreaDown  = ui->ParkArea2;
    RoadPath      = ui->RoadPath;
    Entence       = ui->Entence;
    Exit          = ui->Exit;
    entenceVerify = ui->entenceVerify;
    exitVerify    = ui->exitVerify;
    freeArea      = ui->freeArea;
    RandomCar     = ui->RandomCar;
    MessageBox    = ui->MessageBox;
    timeDisplayer = ui->timeDisplay;

}

void MainWindow::timeDone(){
    if(!Entence->isVisible()){
        Entence->setVisible(true);
    }
    if(toPosition!=-1){
        if(currentEntenceMovementPosition>toPosition){
            waitTwoSecondEntence=2;
            toPosition=-1;
            currentEntenceMovementPosition=0;
        }else{
            painterEntrance();
        }
    }

    if(toPosition==-1&&waitTwoSecondEntence-->-1){
        if(waitTwoSecondEntence==0){
            int position = validateCard.getTakenByCardNum(randomCardId);
            int row=position/MAX_NUM_EACH_COLUMN;
            int column=position%MAX_NUM_EACH_COLUMN;
            buttonArray[row][column]->setObjectName(randomCardId);
            buttonArray[row][column]->setStyleSheet("QPushButton{background:red;height:180px}");
            movementPathArray[column]->setStyleSheet("QPushButton{background:black;width:10px;height:10px;border-radius:5px;margin-left:30px;margin-right:30px;}");
            waitTwoSecondEntence=-1;
            timer->stop();
            isEntencing=false;
        }
    }
}
void MainWindow::timeExitDone(){
    if(ExitTakenArea->isVisible()&&!Exit->isVisible()){
        ExitTakenArea->setVisible(false);
        Exit->setVisible(true);
        timerExit->stop();
        waitTwoSecondExit=2;
        isExiting=false;
    }
    if(!Exit->isVisible()){
        movementPathArray[MAX_NUM_EACH_COLUMN-1]->setStyleSheet("QPushButton{background:black;width:10px;height:10px;border-radius:5px;margin-left:30px;margin-right:30px;}");
        ExitTakenArea->setStyleSheet("QPushButton{background:red;width:180px;height:60px}");
        ExitTakenArea->setVisible(true);
    }
    if(waitTwoSecondExit>-1&&fromPosition!=-1){
        waitTwoSecondExit--;
        qDebug()<<QString("counter");
        if(waitTwoSecondExit!=0)return;
        int cardIdInt=willingToLeaveCar->objectName().toInt();
        int position=validateCard.getTakenByCardNum(cardIdInt>10?QString("0000%1").arg(cardIdInt):QString("00000%1").arg(cardIdInt));
        int row=position/MAX_NUM_EACH_COLUMN;
        int column=position%MAX_NUM_EACH_COLUMN;
        buttonArray[row][column]->setStyleSheet("QPushButton{background:green;height:180px}");
        buttonArray[row][column]->setText("");
        currentExitMovementPosition=column;
        movementPathArray[column]->setStyleSheet("QPushButton{background:yellow;width:10px;height:10px;border-radius:5px;margin-left:30px;margin-right:30px;}");
    }

    if(fromPosition!=-1&&waitTwoSecondExit<=0){
        if(currentExitMovementPosition==MAX_NUM_EACH_COLUMN){
            fromPosition=-1;
            Card card = Card(willingToLeaveCar->objectName());
            card.setStatus(true);
            validateCard.leaveCar(card);
            if(Exit->isVisible()){
                Exit->setVisible(false);
            }
        }else{
            qDebug()<<QString("phase two :%1").arg(waitTwoSecondExit);
//            qDebug()<<QString("current exit%1").arg(currentExitMovementPosition);
            painterExit();
//            qDebug()<<QString("current exit%2").arg(currentExitMovementPosition);
        }
    }
}

void MainWindow::setTakenArea(Card card){
    int position = card.getTaken();
    if((position < 0) || (position >= 2 * MAX_NUM_EACH_COLUMN))
        return;
    int column = position / MAX_NUM_EACH_COLUMN;
    int offset = position % MAX_NUM_EACH_COLUMN;
    buttonArray[column][offset]->setStyleSheet("QPushButton{background:red;height:180px}");
    if(card.getCardNum() != "AAAAAA"){
        buttonArray[column][offset]->setText(card.getCardNum());
        buttonArray[column][offset]->setObjectName(card.getCardNum());
    }
}

void MainWindow::setPreTakenArea(Card *card){
    int posi  = card->getTaken();
    if((posi < 0) || (posi >= 2 * MAX_NUM_EACH_COLUMN))
        return;
    int column = posi / MAX_NUM_EACH_COLUMN;
    int offset = posi % MAX_NUM_EACH_COLUMN;
    qDebug() << "setTempTakenArea:" << "column :" << column << " offset: "<< offset;
    buttonArray[column][offset]->setText(QString("%1").arg(randomCardId));
    buttonArray[column][offset]->setObjectName(QString("%1").arg(randomCardId));
    buttonArray[column][offset]->setStyleSheet("QPushButton{background:gray;height:180px}");
}

void MainWindow::setLeaveArea(Card *card){
    int posi = card->getTaken();
    if((posi < 0) || (posi >= 2 * MAX_NUM_EACH_COLUMN))
        return;
    int column = posi / MAX_NUM_EACH_COLUMN;
    int offset = posi % MAX_NUM_EACH_COLUMN;
    qDebug() << "setLeaveArea:" << "column :" << column << " offset: "<< offset;
    buttonArray[column][offset]->setText("");
    buttonArray[column][offset]->setObjectName("-1");
    buttonArray[column][offset]->setStyleSheet("QPushButton{background:green;height:180px}");

}

void MainWindow::restoreSqlDate(){
    //restore date from sql
    qDebug()<<"###################ParkSystem start###################";
    Card *cardList = validateCard.initialDataSource();
    parkSystem.setParkAreaArray(cardList);
    qDebug() << "breaken point";
    for(int i = 0; i < 2 * MAX_NUM_EACH_COLUMN; i++){
        setTakenArea(cardList[i]);
    }
    freeArea->display(parkSystem.getFreeArea());
}

void MainWindow::disposalEntrance(){

    // 随机生成员工卡号
    Card * card = Card::randomGenerate();
    randomCardId = card->getCardNum();
    RandomCar->setText(randomCardId);

    // 检测员工卡是否合法
    if(validateCard.checkCardValidation(*card)){
        card->setLeaveTime(getTimeRecord()); // 设置随机离开时间
        cardList.push_back(card);            // 放入优先队列
        //bubble sort
        for(uint j = 0; j < cardList.size() - 1 ; j++){
            for( uint i = 0; i < cardList.size() - 1 - j ; i++){
                if( cardList[i]->getLeaveTime() < cardList[i+1]->getLeaveTime() ){
                    Card * temp = cardList[i];
                    cardList[i] = cardList[i+1];
                    cardList[i+1] = temp;
                }
            }
        }

//        MessageBox->setText(QString("%1").arg("Park car successful!"));

        Entence->setVisible(false); // 抬起栏杆
        int parkPosition = parkSystem.selectPosNearEntrance();  // 选择离入口最近空车位
        if(parkPosition == -1){
              qDebug() << "park is full";
              return;
        }

//        qDebug()<<QString("parkPosition is %1").arg(parkPosition%MAX_NUM_EACH_COLUMN);

        card->setTaken(parkPosition); // 设置停车位置信息
        setPreTakenArea(card);        // 设置gui界面
        validateCard.parkCar(*card);  // 记录停车信息
        forwardCards.push_back(new CardControl(-1,parkPosition % MAX_NUM_EACH_COLUMN ,card,CardControl::WAIT2)); // 放入车道记录队列
        waitTwoSecondEntence = 2; // 开始进入栏杆时间倒数
    }else{
        MessageBox->setText(QString("%1").arg("Park car failed, please check your card!")); // 员工卡不合法 提示信息
    }

    freeArea->display(parkSystem.getFreeArea()); // 显示当前剩余车位数
}


void MainWindow::disposalExit(){

    Card * card = cardList[cardList.size() - 1];
    card->setStatus(true);

    if(validateCard.validateLeave(card)){
        cardList.pop_back();  // 从优先队列离开
        parkSystem.exitCar(card); // 记录离开信息
        setLeaveArea(card);
        forwardCards.push_back(new CardControl(card->getTaken()%MAX_NUM_EACH_COLUMN,MAX_NUM_EACH_COLUMN - 1,card,CardControl::RUN)); // 放入车道记录队列
    }else{
    }

    freeArea->display(parkSystem.getFreeArea());
}

void MainWindow::ParkAnimationFinished(){
    if(animationParkPosition == -1)
        return;
    Card *card = new Card("AAAAAA");
    card->setTaken(animationParkPosition);
    card->setStatus(true);
    setTakenArea(*card);
}

int MainWindow::getTimeRecord()
{
    return timeRecord->hour()*3600 + timeRecord->minute()*60 + timeRecord->second();
}

void MainWindow::movePathPainter(){


    if(forwardCards.size() > 1){
    //  bubble sort - decrease
       for(uint j = 0; j < forwardCards.size() - 1 ; j++){
           for(uint i = 0; i < forwardCards.size() - 1 - j ; i++){
               if( forwardCards[i]->getFrom() < forwardCards[i+1]->getFrom() ){
                   CardControl * temp = forwardCards[i];
                   forwardCards[i] = forwardCards[i+1];
                   forwardCards[i+1] = temp;
               }
           }
       }
    }

    for (std::vector<CardControl*>::iterator it = forwardCards.begin(); it != forwardCards.end();it++ ){
        if(forwardCards.empty())
            return;


        qDebug() <<(*it)->getCard()->getCardNum() << (*it)->getFrom() << (*it)->getTo() << (*it)->getStatus() << (*it)->getCard()->getTaken();
        if(CardControl::ARRIVED == (*it)->getStatus()){
            if((*it)->getCard()->getStatus()){
                doLeave((*it)->getFrom());
            }else{
                doArrive((*it)->getCard()->getTaken());
            }
            forwardCards.erase(it);
            continue;
        }
        if(CardControl::RUN == (*it)->changeStatus()){
            if((*it)->getCard()->getStatus()){
                doLeavePath((*it)->changePosi());
            }else{
                doMovePath((*it)->changePosi());
            }
        }

        if(it != forwardCards.begin() && (*it)->getFrom() == (*(it - 1))->getFrom() + 1 && ((*(it - 1))->getStatus() == CardControl::WAIT1 ||(*(it - 1))->getStatus() == CardControl::WAIT2))
            (*it)->setStatus(CardControl::WAIT1);
    }
}

void MainWindow::doMovePath(int p){
    if(p != 0)
        movementPathArray[p-1]->setStyleSheet("QPushButton{background:black;width:10px;height:10px;border-radius:5px;margin-left:30px;margin-right:30px;}");
    movementPathArray[p]->setStyleSheet("QPushButton{background:green;width:10px;height:10px;border-radius:5px;margin-left:30px;margin-right:30px;}");
}

void MainWindow::doLeavePath(int p){
    if(p != 0)
        movementPathArray[p-1]->setStyleSheet("QPushButton{background:black;width:10px;height:10px;border-radius:5px;margin-left:30px;margin-right:30px;}");
    movementPathArray[p]->setStyleSheet("QPushButton{background:yellow;width:10px;height:10px;border-radius:5px;margin-left:30px;margin-right:30px;}");

}

void MainWindow::doArrive(int p)
{
    buttonArray[p / MAX_NUM_EACH_COLUMN][p % MAX_NUM_EACH_COLUMN]->setStyleSheet("QPushButton{background:red;height:180px}");
    movementPathArray[p % MAX_NUM_EACH_COLUMN]->setStyleSheet("QPushButton{background:black;width:10px;height:10px;border-radius:5px;margin-left:30px;margin-right:30px;}");
}

void MainWindow::doLeave(int p)
{
//    buttonArray[p / MAX_NUM_EACH_COLUMN][p % MAX_NUM_EACH_COLUMN]->setStyleSheet("QPushButton{background:red;height:180px}");
    movementPathArray[p % MAX_NUM_EACH_COLUMN]->setStyleSheet("QPushButton{background:black;width:10px;height:10px;border-radius:5px;margin-left:30px;margin-right:30px;}");
}

void MainWindow::painterExit(){
    if(currentExitMovementPosition!=0)
        movementPathArray[currentExitMovementPosition-1]->setStyleSheet("QPushButton{background:black;width:10px;height:10px;border-radius:5px;margin-left:30px;margin-right:30px;}");
    movementPathArray[currentExitMovementPosition]->setStyleSheet("QPushButton{background:yellow;width:10px;height:10px;border-radius:5px;margin-left:30px;margin-right:30px;}");
    currentExitMovementPosition++;
}
void MainWindow::painterEntrance(){
    if(currentEntenceMovementPosition!=0)
        movementPathArray[currentEntenceMovementPosition-1]->setStyleSheet("QPushButton{background:black;width:10px;height:10px;border-radius:5px;margin-left:30px;margin-right:30px;}");
    movementPathArray[currentEntenceMovementPosition]->setStyleSheet("QPushButton{background:green;width:10px;height:10px;border-radius:5px;margin-left:30px;margin-right:30px;}");
    currentEntenceMovementPosition++;
}

void MainWindow::randomTimerEntranceDone(){
    // 管理抬杆
    if(waitTwoSecondEntence > 0){
        waitTwoSecondEntence --;
        if(Entence->isVisible()){
            Entence->setVisible(false);
        }
        return;
    }else{
        isEntencing = false;
        if(!Entence->isVisible()){
            Entence->setVisible(true);
        }
    }


//    if(waitTwoSecondEntence > 0)
//        return;

    // 当有空车位时，触发刷卡事件
    if(parkSystem.getFreeArea()>0){
        emit verifyEntranceSignals();
    }
}

void MainWindow::randomTimerExitDone(){
    // 场内有车时，触发车辆离开事件
    if(parkSystem.getFreeArea() < MAX_NUM_EACH_COLUMN *2 && parkSystem.getFreeArea() < 18){
       Card * leavingCard = cardList[cardList.size() - 1];
       qDebug() << leavingCard->getLeaveTime() << leavingCard->getCardNum() << getTimeRecord();
       if(leavingCard->getLeaveTime() > getTimeRecord()) return; // 判断最近将要离场车辆是否到期
       emit verifyExitSignals();
    }
}
MainWindow::~MainWindow()
{
    delete ui;
}
